package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.logi.sys.bo.LogiWaybillAgentPayQueryBo;
import com.piggy.logi.sys.bo.LogiWaybillAgentPayRecordEditBo;
import com.piggy.logi.sys.domain.LogiSysBaseConfig;
import com.piggy.logi.sys.domain.LogiWaybillAgentPay;
import com.piggy.logi.sys.domain.LogiWaybillAgentPayRecord;
import com.piggy.logi.sys.enums.SettleStatusEnum;
import com.piggy.logi.sys.mapper.LogiWaybillAgentPayMapper;
import com.piggy.logi.sys.service.ILogiSysBaseConfigService;
import com.piggy.logi.sys.service.ILogiWaybillAgentPayRecordService;
import com.piggy.logi.sys.service.ILogiWaybillAgentPayService;
import com.piggy.logi.sys.vo.LogiWaybillAgentPayVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * 代收货款Service业务层处理
 *
 * @author fengxy
 * @date 2023/10/17 21:54
 **/
@Slf4j
@Service
public class LogiWaybillAgentPayServiceImpl extends ServiceImpl<LogiWaybillAgentPayMapper, LogiWaybillAgentPay> implements ILogiWaybillAgentPayService {

    @Resource
    private ILogiWaybillAgentPayRecordService logiWaybillAgentPayRecordService;

    @Resource
    private ILogiSysBaseConfigService logiSysBaseConfigService;

    @Override
    public TableDataInfo<LogiWaybillAgentPayVo> queryPageList(LogiWaybillAgentPayQueryBo bo) {
        return PageUtils.buildDataInfo(baseMapper.queryPageList(PageUtils.buildPage(bo), bo));
    }

    @Override
    public LogiWaybillAgentPayVo queryById(Long id) {
        LogiWaybillAgentPayVo agentPayVo = baseMapper.getVoById(id);
        if (ObjectUtil.isNull(agentPayVo)) {
            throw new GlobalException("代收货款记录id为空");
        }
        return agentPayVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmPay(LogiWaybillAgentPayRecordEditBo bo) {
        // 获取代收货款记录
        LogiWaybillAgentPay agentPay = getById(bo.getAgentPayId());
        if (ObjectUtil.isNull(agentPay)) {
            throw new GlobalException("代收货款记录不存在");
        }
        // 支付金额不能大于实收余额
        if (bo.getPayAmount().compareTo(agentPay.getRealBalance()) > 0) {
            throw new GlobalException("支付金额不能大于实收余额");
        }
        // 新增收款记录
        LogiWaybillAgentPayRecord record = BeanUtil.toBean(bo, LogiWaybillAgentPayRecord.class);
        boolean success = logiWaybillAgentPayRecordService.save(record);
        if (!success) {
            throw new GlobalException("新增收款记录失败");
        }
        // 增加实收金额、减少实收余额、收款记录数量+1
        success = update(Wrappers.lambdaUpdate(LogiWaybillAgentPay.class)
                .set(LogiWaybillAgentPay::getRealAmount, agentPay.getRealAmount().add(record.getPayAmount()))
                .set(LogiWaybillAgentPay::getRealBalance,agentPay.getRealBalance().subtract(record.getPayAmount()))
                .set(LogiWaybillAgentPay::getRecordNum, agentPay.getRecordNum() + 1)
                .eq(LogiWaybillAgentPay::getId, agentPay.getId()));
        if (!success) {
            throw new GlobalException("修改实收金额、实收余额、收款记录数量失败");
        }
    }

    @Override
    public List<LogiWaybillAgentPayRecord> payList(Long id) {
        return logiWaybillAgentPayRecordService.list(Wrappers.lambdaQuery(LogiWaybillAgentPayRecord.class)
                .eq(LogiWaybillAgentPayRecord::getAgentPayId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRecord(LogiWaybillAgentPayRecordEditBo bo) {
        // 校验参数
        if (ObjectUtil.isNull(bo.getId())) {
            throw new GlobalException("收款记录id为空");
        }
        // 查询老的收款记录
        LogiWaybillAgentPayRecord oldRecord = logiWaybillAgentPayRecordService.getById(bo.getId());
        if (ObjectUtil.isNull(oldRecord)) {
            throw new GlobalException("收款记录不存在");
        }
        // 获取代收货款记录
        LogiWaybillAgentPay agentPay = getById(oldRecord.getAgentPayId());
        if (ObjectUtil.isNull(agentPay)) {
            throw new GlobalException("代收货款记录不存在");
        }
        // 获取新的实收余额
        BigDecimal realBalance = agentPay.getRealBalance().add(oldRecord.getPayAmount()).subtract(bo.getPayAmount());
        // 实收余额不能小于0
        if (realBalance.compareTo(BigDecimal.ZERO) < 0) {
            throw new GlobalException("实收余额不能小于0");
        }
        // 修改收款记录信息
        LogiWaybillAgentPayRecord newRecord = BeanUtil.toBean(bo, LogiWaybillAgentPayRecord.class);
        boolean success = logiWaybillAgentPayRecordService.updateById(newRecord);
        if (!success) {
            throw new GlobalException("修改收款记录信息失败");
        }
        // 更新实收金额、实收余额
        success = update(Wrappers.lambdaUpdate(LogiWaybillAgentPay.class)
                .set(LogiWaybillAgentPay::getRealAmount, agentPay.getRealAmount().subtract(oldRecord.getPayAmount()).add(newRecord.getPayAmount()))
                .set(LogiWaybillAgentPay::getRealBalance, realBalance)
                .eq(LogiWaybillAgentPay::getId, agentPay.getId()));
        if (!success) {
            throw new GlobalException("修改实收金额、实收余额失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRecord(Long id) {
        // 查询收款记录
        LogiWaybillAgentPayRecord record = logiWaybillAgentPayRecordService.getById(id);
        if (ObjectUtil.isNull(record)) {
            throw new GlobalException("收款记录不存在");
        }
        // 获取代收货款记录
        LogiWaybillAgentPay agentPay = getById(record.getAgentPayId());
        if (ObjectUtil.isNull(agentPay)) {
            throw new GlobalException("代收货款记录不存在");
        }
        // 删除收款记录
        boolean success = logiWaybillAgentPayRecordService.removeById(record.getId());
        if (!success) {
            throw new GlobalException("删除收款记录失败");
        }
        // 减少实收金额、增加实收余额、收款记录数量-1
        success = update(Wrappers.lambdaUpdate(LogiWaybillAgentPay.class)
                .set(LogiWaybillAgentPay::getRealAmount, agentPay.getRealAmount().subtract(record.getPayAmount()))
                .set(LogiWaybillAgentPay::getRealBalance,agentPay.getRealBalance().add(record.getPayAmount()))
                .set(LogiWaybillAgentPay::getRecordNum, agentPay.getRecordNum() - 1)
                .eq(LogiWaybillAgentPay::getId, agentPay.getId()));
        if (!success) {
            throw new GlobalException("修改实收金额、实收余额、收款记录数量失败");
        }
    }

    @Override
    public void confirmSettle(Long id) {
        // 查询代收货款信息
        LogiWaybillAgentPay agentPay = getById(id);
        if (ObjectUtil.isNull(agentPay)) {
            throw new GlobalException("代收货款记录不存在");
        }
        // 校验状态是否为未结清
        if (SettleStatusEnum.NOT_SETTLE.getCode() != agentPay.getStatus()) {
            throw new GlobalException("请选择未结清的代收货款记录");
        }
        // 校验代收货款余额是否为0
        LogiSysBaseConfig sysBaseConfig = logiSysBaseConfigService.getBaseConfig(agentPay.getDeptId());
        if (sysBaseConfig.getAgentPaySettled() == 1 && BigDecimal.ZERO.compareTo(agentPay.getRealBalance()) != 0) {
            throw new GlobalException("实收余额不为0");
        }
        // 修改状态未：已结清
        boolean success = update(Wrappers.lambdaUpdate(LogiWaybillAgentPay.class)
                .set(LogiWaybillAgentPay::getStatus, SettleStatusEnum.SETTLED.getCode())
                .eq(LogiWaybillAgentPay::getId, agentPay.getId()));
        if (!success) {
            throw new GlobalException("修改结清状态状态已结清失败");
        }
    }

    @Override
    public void cancelSettle(Long id) {
        // 查询代收货款信息
        LogiWaybillAgentPay agentPay = getById(id);
        if (ObjectUtil.isNull(agentPay)) {
            throw new GlobalException("代收货款记录不存在");
        }
        // 判断状态是否为已结清
        if (SettleStatusEnum.SETTLED.getCode() != agentPay.getStatus()) {
            throw new GlobalException("请选择已结清的代收货款记录");
        }
        // 修改状态未：未结清
        boolean success = update(Wrappers.lambdaUpdate(LogiWaybillAgentPay.class)
                .set(LogiWaybillAgentPay::getStatus, SettleStatusEnum.NOT_SETTLE.getCode())
                .eq(LogiWaybillAgentPay::getId, agentPay.getId()));
        if (!success) {
            throw new GlobalException("修改结清状态状态未结清失败");
        }
    }

    @Override
    public void removeByUK(Long deptId, Long waybillId) {
        baseMapper.removeByUK(deptId, waybillId);
    }
}
